package dao

import (
	"context"
	"fmt"
	"gorm.io/gorm"
	"order_srv/basic/config"
	"order_srv/handler/models"
	"time"
)

// CreateLog 创建操作日志
func CreateLog(ctx context.Context, log *models.OperationLog) error {
	return config.DB.WithContext(ctx).Create(log).Error
}

// CreateLogWithTx 在事务中创建操作日志
func CreateLogWithTx(tx *gorm.DB, log *models.OperationLog) error {
	return tx.Create(log).Error
}

// GetLogsByUser 根据用户ID获取操作日志
func GetLogsByUser(ctx context.Context, userID string, page, pageSize int32) ([]models.OperationLog, int64, error) {
	var logs []models.OperationLog
	var total int64

	query := config.DB.WithContext(ctx).Model(&models.OperationLog{}).Where("user_id = ?", userID)

	// 获取总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, fmt.Errorf("获取日志总数失败: %w", err)
	}

	// 分页查询
	offset := (page - 1) * pageSize
	if err := query.Offset(int(offset)).Limit(int(pageSize)).Order("created_at DESC").Find(&logs).Error; err != nil {
		return nil, 0, fmt.Errorf("获取日志列表失败: %w", err)
	}

	return logs, total, nil
}

// GetLogsByModule 根据模块获取操作日志
func GetLogsByModule(ctx context.Context, module string, page, pageSize int32) ([]models.OperationLog, int64, error) {
	var logs []models.OperationLog
	var total int64

	query := config.DB.WithContext(ctx).Model(&models.OperationLog{}).Where("module = ?", module)

	// 获取总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, fmt.Errorf("获取日志总数失败: %w", err)
	}

	// 分页查询
	offset := (page - 1) * pageSize
	if err := query.Offset(int(offset)).Limit(int(pageSize)).Order("created_at DESC").Find(&logs).Error; err != nil {
		return nil, 0, fmt.Errorf("获取日志列表失败: %w", err)
	}

	return logs, total, nil
}

// GetLogsByResource 根据资源获取操作日志
func GetLogsByResource(ctx context.Context, resourceType, resourceID string, page, pageSize int32) ([]models.OperationLog, int64, error) {
	var logs []models.OperationLog
	var total int64

	query := config.DB.WithContext(ctx).Model(&models.OperationLog{}).Where("resource_type = ? AND resource_id = ?", resourceType, resourceID)

	// 获取总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, fmt.Errorf("获取日志总数失败: %w", err)
	}

	// 分页查询
	offset := (page - 1) * pageSize
	if err := query.Offset(int(offset)).Limit(int(pageSize)).Order("created_at DESC").Find(&logs).Error; err != nil {
		return nil, 0, fmt.Errorf("获取日志列表失败: %w", err)
	}

	return logs, total, nil
}

// GetLogsByTimeRange 根据时间范围获取操作日志
func GetLogsByTimeRange(ctx context.Context, startTime, endTime time.Time, page, pageSize int32) ([]models.OperationLog, int64, error) {
	var logs []models.OperationLog
	var total int64

	query := config.DB.WithContext(ctx).Model(&models.OperationLog{}).Where("created_at BETWEEN ? AND ?", startTime, endTime)

	// 获取总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, fmt.Errorf("获取日志总数失败: %w", err)
	}

	// 分页查询
	offset := (page - 1) * pageSize
	if err := query.Offset(int(offset)).Limit(int(pageSize)).Order("created_at DESC").Find(&logs).Error; err != nil {
		return nil, 0, fmt.Errorf("获取日志列表失败: %w", err)
	}

	return logs, total, nil
}

// GetLogsByCondition 根据条件获取操作日志
func GetLogsByCondition(ctx context.Context, condition *LogQueryCondition) ([]models.OperationLog, int64, error) {
	var logs []models.OperationLog
	var total int64

	query := config.DB.WithContext(ctx).Model(&models.OperationLog{})

	// 构建查询条件
	if condition.UserID != "" {
		query = query.Where("user_id = ?", condition.UserID)
	}
	if condition.Module != "" {
		query = query.Where("module = ?", condition.Module)
	}
	if condition.Operation != "" {
		query = query.Where("operation = ?", condition.Operation)
	}
	if condition.ResourceType != "" {
		query = query.Where("resource_type = ?", condition.ResourceType)
	}
	if condition.ResourceID != "" {
		query = query.Where("resource_id = ?", condition.ResourceID)
	}
	if condition.LogType != "" {
		query = query.Where("log_type = ?", condition.LogType)
	}
	if condition.Result != "" {
		query = query.Where("result = ?", condition.Result)
	}
	if condition.StartTime != nil {
		query = query.Where("created_at >= ?", condition.StartTime)
	}
	if condition.EndTime != nil {
		query = query.Where("created_at <= ?", condition.EndTime)
	}
	if condition.IPAddress != "" {
		query = query.Where("ip_address = ?", condition.IPAddress)
	}

	// 获取总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, fmt.Errorf("获取日志总数失败: %w", err)
	}

	// 分页查询
	offset := (condition.Page - 1) * condition.PageSize
	if err := query.Offset(int(offset)).Limit(int(condition.PageSize)).Order("created_at DESC").Find(&logs).Error; err != nil {
		return nil, 0, fmt.Errorf("获取日志列表失败: %w", err)
	}

	return logs, total, nil
}

// GetLogStatistics 获取日志统计信息
func GetLogStatistics(ctx context.Context, startTime, endTime time.Time) (map[string]interface{}, error) {
	var stats map[string]interface{} = make(map[string]interface{})

	query := config.DB.WithContext(ctx).Model(&models.OperationLog{}).Where("created_at BETWEEN ? AND ?", startTime, endTime)

	// 总日志数
	var totalCount int64
	if err := query.Count(&totalCount).Error; err != nil {
		return nil, fmt.Errorf("获取总日志数失败: %w", err)
	}
	stats["total_count"] = totalCount

	// 按模块统计
	var moduleStats []struct {
		Module string `json:"module"`
		Count  int64  `json:"count"`
	}
	if err := query.Select("module, COUNT(*) as count").Group("module").Scan(&moduleStats).Error; err != nil {
		return nil, fmt.Errorf("获取模块统计失败: %w", err)
	}
	stats["module_stats"] = moduleStats

	// 按操作类型统计
	var operationStats []struct {
		Operation string `json:"operation"`
		Count     int64  `json:"count"`
	}
	if err := query.Select("operation, COUNT(*) as count").Group("operation").Scan(&operationStats).Error; err != nil {
		return nil, fmt.Errorf("获取操作统计失败: %w", err)
	}
	stats["operation_stats"] = operationStats

	// 按结果统计
	var resultStats []struct {
		Result string `json:"result"`
		Count  int64  `json:"count"`
	}
	if err := query.Select("result, COUNT(*) as count").Group("result").Scan(&resultStats).Error; err != nil {
		return nil, fmt.Errorf("获取结果统计失败: %w", err)
	}
	stats["result_stats"] = resultStats

	// 按用户统计
	var userStats []struct {
		UserID   string `json:"user_id"`
		UserName string `json:"user_name"`
		Count    int64  `json:"count"`
	}
	if err := query.Select("user_id, user_name, COUNT(*) as count").Group("user_id, user_name").Order("count DESC").Limit(10).Scan(&userStats).Error; err != nil {
		return nil, fmt.Errorf("获取用户统计失败: %w", err)
	}
	stats["user_stats"] = userStats

	// 平均响应时间
	var avgResponseTime float64
	if err := query.Select("AVG(response_time)").Where("response_time > 0").Scan(&avgResponseTime).Error; err != nil {
		return nil, fmt.Errorf("获取平均响应时间失败: %w", err)
	}
	stats["avg_response_time"] = avgResponseTime

	return stats, nil
}

// DeleteOldLogs 删除旧日志
func DeleteOldLogs(ctx context.Context, beforeTime time.Time) error {
	return config.DB.WithContext(ctx).Where("created_at < ?", beforeTime).Delete(&models.OperationLog{}).Error
}

// LogQueryCondition 日志查询条件
type LogQueryCondition struct {
	UserID       string     `json:"user_id"`
	Module       string     `json:"module"`
	Operation    string     `json:"operation"`
	ResourceType string     `json:"resource_type"`
	ResourceID   string     `json:"resource_id"`
	LogType      string     `json:"log_type"`
	Result       string     `json:"result"`
	StartTime    *time.Time `json:"start_time"`
	EndTime      *time.Time `json:"end_time"`
	IPAddress    string     `json:"ip_address"`
	Page         int32      `json:"page"`
	PageSize     int32      `json:"page_size"`
}

// CreateOperationLog 创建操作日志的便捷函数
func CreateOperationLog(ctx context.Context, logType, module, operation, resourceType, resourceID, userID, userName, userType, description string) error {
	log := &models.OperationLog{
		LogType:      logType,
		Module:       module,
		Operation:    operation,
		ResourceType: resourceType,
		ResourceID:   resourceID,
		UserID:       userID,
		UserName:     userName,
		UserType:     userType,
		Result:       models.ResultSuccess,
		Description:  description,
		CreatedAt:    time.Now(),
	}
	return CreateLog(ctx, log)
}

// CreateErrorLog 创建错误日志的便捷函数
func CreateErrorLog(ctx context.Context, module, operation, resourceType, resourceID, userID, userName, userType, errorMessage, description string) error {
	log := &models.OperationLog{
		LogType:      models.LogTypeError,
		Module:       module,
		Operation:    operation,
		ResourceType: resourceType,
		ResourceID:   resourceID,
		UserID:       userID,
		UserName:     userName,
		UserType:     userType,
		Result:       models.ResultError,
		ErrorMessage: errorMessage,
		Description:  description,
		CreatedAt:    time.Now(),
	}

	return CreateLog(ctx, log)
}
